package com.zfast.config.junit.util;

import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.zfast.forge.constant.SysConstant;
import com.zfast.forge.navigation.Coordinate;
import com.zfast.forge.pojo.CustomBigDecimal;
import com.zfast.forge.pojo.bo.PlayerInstance;
import com.zfast.forge.qlExpress.BadFunctions;
import com.zfast.forge.qlExpress.FormulaEnum;
import com.zfast.forge.qlExpress.QLExpressUtil;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;

import java.math.BigDecimal;

/**
 * @author zgn
 * @Description: simJunit
 * @date 2022/1/13 0013
 */
public class 阿里公式Junit {
    @Test
    public void egMax() {//e.g.
        //region 1.模拟数据
        System.out.println("--------------------Start--------------------");
        //endregion

        //region 2.数据处理
        System.out.println("--------------------Deal--------------------");
        //endregion

        //region 3.数据展示
        System.out.println("--------------------Done--------------------");
        //endregion
    }

    @Test
    public void egMin() {//e.g.
        System.out.println();
    }

    ExpressRunner runner = new ExpressRunner(true, false);

    @Test
    public void Express_引入_egMin() {
        //1.选择公式
        //String express ="level/phase+health^2";
        String express = FormulaEnum.test002.getValue();//成长潜力

        //2.赋值
        DefaultContext<String, Object> context = new DefaultContext();

        //映射替换过滤 level*phase/health
        /*context.put("level",1);
        context.put("phase",2);*/
        context.put("health",3);

        try {
            //Object execute = runner.execute("health^3", context, null, true, false);
            //System.out.println(execute);

            Object execute1 = QLExpressUtil.execute(FormulaEnum.test002, context, runner);
            System.out.println(execute1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SneakyThrows
    @Test
    public void Express_开更_egMin() {//e.g.
        String express ="√([1,2,2])";
        DefaultContext<String, Object> context = new DefaultContext();
        //https://blog.hhui.top/hexblog/2021/06/28/210628-QlExpress使用姿势三-Function与方法绑定/
        runner.addFunctionOfClassMethod("√", BadFunctions.class.getName(), "squareRoot", new Class[]{Object[].class}, null);
        Object execute = runner.execute(express, context, null, true, false);
        System.out.println(execute);
    }

    @SneakyThrows
    @Test
    public void Express_复杂公式_egMin() {
        //1.选择公式
        String express = FormulaEnum.VelocityDecomposition.getValue();

        //2.赋值
        DefaultContext<String, Object> context = new DefaultContext();
        context.put("X",1);
        context.put("Y",2);
        context.put("Z",2);
        context.put("V",9);

        runner.addFunctionOfClassMethod("√", BadFunctions.class.getName(), "squareRoot", new Class[]{Object[].class}, null);

        //3.计算
        Double[] execute = (Double[]) runner.execute(express, context, null, true, false);

        for (int i = 0; i < execute.length; i++) {
            Double aDouble = execute[i];
            System.out.println(aDouble);
        }
    }

    @SneakyThrows
    @Test
    public void Express_复杂公式2_util优化_egMin() {
        //1.选择公式
        String express = FormulaEnum.VelocityDecomposition.getValue();

        //2.赋值
        DefaultContext<String, Object> context = new DefaultContext();
        context.put("X",1);
        context.put("Y",1);
        context.put("Z",1);
        context.put("V",13.6944);

        //QLExpressUtil
        QLExpressUtil.autoFunctionsBind(runner,FormulaEnum.VelocityDecomposition);
        //runner.addFunctionOfClassMethod("√", BadFunctions.class.getName(), "squareRoot", new Class[]{Object[].class}, null);

        //3.计算
        Double[] execute = (Double[]) runner.execute(express, context, null, true, false);

        for (int i = 0; i < execute.length; i++) {
            Double aDouble = execute[i];
            System.out.println(aDouble);
        }
    }

    @SneakyThrows
    @Test
    public void Express_复杂公式3_util优化_egMin() {
        //2.赋值
        DefaultContext<String, Object> context = new DefaultContext();
        QLExpressUtil.autoFunctionsBind(runner, FormulaEnum.VelocityDecomposition);

        context.put("speed",new Coordinate("1,2,2"));
        context.put("V",13.6944);

        Coordinate result=(Coordinate)QLExpressUtil.execute(FormulaEnum.VelocityDecomposition,context,runner);
        System.out.println(result);
    }

    @SneakyThrows
    @Test
    public void Express_实战使用_util优化_egMin() {
        //region 赋值
        DefaultContext<String, Object> context = new DefaultContext();
        context.put("F",700);
        context.put("M",0.0055);
        context.put("V",136.9444);
        context.put("T",0.004);
        //endregion

        //公式
        //2.1 极限手部发力效率
        BigDecimal execute = (BigDecimal) QLExpressUtil.execute(FormulaEnum.testHandStrengthToSpeed,context,runner);

        //结果
        System.out.println(execute);
    }

    @Test
    public void BigDecimal_egMin() {//e.g.
        BigDecimal number = new BigDecimal("3.6055");
        BigDecimal square = number.pow(2);
        BigDecimal squareRoot = new BigDecimal(Math.sqrt(13));
        System.out.println(square);
        System.out.println(squareRoot);
        int scale=4;
        int ROUNDmodel=BigDecimal.ROUND_HALF_UP;
        BigDecimal price = new BigDecimal("5.5564");
        price.setScale(scale);
    }

    @Test
    public void BigDecimal_幂计算_egMin() {//e.g.

        System.out.println(CustomBigDecimal.valueOf(new BigDecimal(3).pow(2)));
    }

    @Test
    public void 坐标系_egMin() {//e.g.
        DefaultContext<String, Object> context = new DefaultContext();
        QLExpressUtil.autoFunctionsBind(runner, FormulaEnum.MovingPoint);

        context.put("initial",new Coordinate("90,50,120"));
        context.put("Vx",2);
        context.put("Vy",2);
        context.put("Vz",90);
        context.put("Ax",2);
        context.put("Ay",2);
        context.put("Az",90);
        context.put("t",30);

        System.out.println(QLExpressUtil.execute(FormulaEnum.MovingPoint,context,runner));
    }

    @Test
    //QLExpress运行后会将所有参数传给context中(同一个context可以更新)
    public void Express_多次使用公式参数是否同步_egMin() {
        //1.选择公式
        String express ="level/phase+health^2";
        String express1="health=level+phase+7+dev";

        //2.赋值
        DefaultContext<String, Object> context = new DefaultContext();

        //映射替换过滤 level*phase/health
        context.put("level",1);
        context.put("phase",2);
        context.put("health",3);

        try {
            Object execute = runner.execute(express, context, null, true, false);

            DefaultContext<String, Object> context1 = new DefaultContext();
            context1.put("dev",8);
            context1.put("level",1);
            context1.put("phase",2);
            context1.put("health",3);
            Object execute1 = runner.execute(express1, context1, null, true, false);
            System.out.print(execute);
            System.out.print(execute1);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    @Test
    //每个表达式的import是独立的
    public void Express_import是否可以复用_egMin() {
        //1.选择公式
        String express = FormulaEnum.convertHandStrengthToSpeed.getValue();
        String express1 = "import com.zfast.forge.pojo.CustomBigDecimal;CustomBigDecimal.valueOf(V)";

        //2.赋值
        PlayerInstance instance=PlayerInstance.builder().hand(2000d).hp(500d).build();
        DefaultContext<String, Object> context = new DefaultContext();
        context.put("instance", instance);

        try {
            Object execute = runner.execute(express, context, null, true, false);
            context.put("V", 9.123456789);
            Object execute1 = runner.execute(express1, context, null, true, false);
            System.out.println(execute);
            System.out.println(execute1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SneakyThrows
    @Test
    public void Express_实战使用_竖直上抛运动公式_egMin() {
        //region 赋值
        DefaultContext<String, Object> context = new DefaultContext();
        context.put("h",1200);
        context.put("v",1);
        context.put("g",-0.98);
        //endregion
    }

    @SneakyThrows
    @Test
    public void Express_实战使用_空气阻力加速度计算_egMin() {
        DefaultContext<String, Object> context = new DefaultContext();
        QLExpressUtil.autoFunctionsBind(runner, FormulaEnum.AirResistanceCalculator);

        context.put("C", SysConstant.dragCoefficient);
        context.put("P", SysConstant.density);
        context.put("S", SysConstant.area);
        context.put("V", 1.1388);
        context.put("M", SysConstant.scale);

        BigDecimal execute = (BigDecimal) QLExpressUtil.execute(FormulaEnum.AirResistanceCalculator, context, runner);
        System.out.println(execute);
    }
}
